/***************************************************************************
 *   Copyright (C) 2007 by Grzegorz Latarowski   *
 *   g.latarowski@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


// gcommon
#include "gexception.h"


// local
#include "roieditor.h"

const char * TAG_ROI_EDITOR = "roiEditor";
const char * TAG_AREAS_DESCRIPTION = "areasDescription";

const char * TAG_ROI              = "roi";
const char * TAG_START_MARKER     = "startMarker";
const char * TAG_END_MARKER       = "endMarker";
const char * TAG_SHUTTER_MARKER   = "shutterMarker";

#define START_MARKER_COLOR    Qt::darkRed
#define BETWEEN_MARKERS_COLOR Qt::white
#define END_MARKER_COLOR      Qt::darkGreen

#define SHUTTER_MARKER_COLOR  Qt::darkBlue



// ===========================================================================
//                              GRoiEditor
// ===========================================================================


// --------------------- GRoiEditor::GRoiEditor() ----------------------------
GRoiEditor::GRoiEditor( QObject * pParent )
	: QGraphicsScene( pParent )
{
		// clear manip items
	_pStartMarker   = 0;
	_pEndMarker     = 0;
	_pShutterMarker = 0;
	_pRoi           = 0;

	_pAlarmIcon         = 0;
	_pAccelExccededIcon = 0;
	
		// setup scene
	this->setItemIndexMethod( QGraphicsScene::NoIndex );
}
// ---------------------------------------------------------------------------


// ---------------------- GRoiEditor::~GRoiEditor() --------------------------
GRoiEditor::~GRoiEditor()
{
	foreach( QGraphicsItem * pItem, this->items() )
	{
		delete pItem;
	}
}
// ---------------------------------------------------------------------------


// ------------------------ GRoiEditor::toXml() ------------------------------
QDomElement GRoiEditor::toXml( QDomDocument & doc )const
{
	QDomElement roiEditorElement = doc.createElement( TAG_ROI_EDITOR );

		// add roi to dom tree 
	if( _pRoi )
	{
		if( isRoiToolVisible() )
		{
			roiEditorElement.appendChild( _pRoi->toXml( doc ) );
		}
	}
		// add startMarker to dom tree 
	if( _pStartMarker )
	{
		if( isStartMarkerVisible() )
		{
			roiEditorElement.appendChild( _pStartMarker->toXml( doc ) );
		}
	}
		// add endMarker to dom tree 
	if( _pEndMarker )
	{
		if( isEndMarkerVisible() )
		{
			roiEditorElement.appendChild( _pEndMarker->toXml( doc ) );
		}
	}
		// add shutterMarker to dom tree 
	if( _pShutterMarker )
	{
		if( isShutterMarkerVisible() )
		{
			roiEditorElement.appendChild( _pShutterMarker->toXml( doc ) );
		}
	}

	return roiEditorElement;
}
// ---------------------------------------------------------------------------


// ------------------------ GRoiEditor::fromXml() ----------------------------
void GRoiEditor::fromXml( const QDomElement & element )
{
	QDomElement roiEditorElement;
		// check if searched node isn't root 
	if( element.tagName() == TAG_ROI_EDITOR )
	{
		roiEditorElement = element;
	}
	else
	{
		roiEditorElement = element.firstChildElement( TAG_ROI_EDITOR );
	}
	
		// if there is no roiEditor node than throw an error
	if( roiEditorElement.isNull() )
	{
		// NOTE Maybe throw?
		return;
// 		throw GDatasetError( tr( "Can not find '%1' node." ).arg( TAG_ROI_EDITOR ) );
	}

	// ====================================================
	// parse rest
	
		// parse roi
	if( _pRoi )
	{
			// add to scene if removed
		if( _pRoi->scene() != this )
		{
			this->addItem( _pRoi );
		}
	_pRoi->disconnect();
		_pRoi->fromXml( roiEditorElement );
	connect( _pRoi, SIGNAL( itemChanged() ),
				this, SIGNAL( roiChanged() ) );
	}
		// parse roi
	if( _pStartMarker )
	{
			// add to scene if removed
		if( _pStartMarker->scene() != this )
		{
			this->addItem( _pStartMarker );
		}
	_pStartMarker->disconnect();
		_pStartMarker->fromXml( roiEditorElement );
	connect( _pStartMarker, SIGNAL( itemChanged() ),
				this, SIGNAL( markersChanged() ) );
	}
		// parse roi
	if( _pEndMarker )
	{
			// add to scene if removed
		if( _pEndMarker->scene() != this )
		{
			this->addItem( _pEndMarker );
		}
	_pEndMarker->disconnect();
		_pEndMarker->fromXml( roiEditorElement );
	connect( _pEndMarker, SIGNAL( itemChanged() ),
				this, SIGNAL( markersChanged() ) );
	}
		// parse roi
	if( _pShutterMarker )
	{
			// add to scene if removed
		if( _pShutterMarker->scene() != this )
		{
			this->addItem( _pShutterMarker );
		}
	_pShutterMarker->disconnect();
		_pShutterMarker->fromXml( roiEditorElement );
	connect( _pShutterMarker, SIGNAL( itemChanged() ),
				this, SIGNAL( shutterChanged() ) );
	}
}
// ---------------------------------------------------------------------------


// ------------------- GRoiEditor::readAreasDescription() --------------------
void GRoiEditor::readAreasDescription( const QDomElement & element )
{
	QDomElement areasDescriptionElement;
		// check if searched node isn't root 
	if( element.tagName() == TAG_AREAS_DESCRIPTION )
	{
		areasDescriptionElement = element;
	}
	else
	{
		areasDescriptionElement = element.firstChildElement( TAG_AREAS_DESCRIPTION );
	}
	
		// if there is no areasDescription node than throw an error
	if( areasDescriptionElement.isNull() )
	{
		throw GDatasetError( tr( "Can not find '%1' node." ).arg( TAG_AREAS_DESCRIPTION ) );
	}

	// proceed
	
	QDomElement roiElement = areasDescriptionElement.firstChildElement( TAG_ROI );
	if( !roiElement.isNull() )
	{
		QVariant showRoi = GXmlElement::variantFromXml( roiElement );
		setRoiToolVisible( showRoi.toBool() );
	}
	QDomElement startMarkerElement = areasDescriptionElement.firstChildElement( TAG_START_MARKER );
	if( !startMarkerElement.isNull() )
	{
		QVariant showStartMarker = GXmlElement::variantFromXml( startMarkerElement );
		setStartMarkerVisible( showStartMarker.toBool() );
	}
	QDomElement endMarkerElement = areasDescriptionElement.firstChildElement( TAG_END_MARKER );
	if( !endMarkerElement.isNull() )
	{
		QVariant showEndMarker = GXmlElement::variantFromXml( endMarkerElement );
		setEndMarkerVisible( showEndMarker.toBool() );
	}
	QDomElement shutterMarkerElement = areasDescriptionElement.firstChildElement( TAG_SHUTTER_MARKER );
	if( !shutterMarkerElement.isNull() )
	{
		QVariant showShutterMarker = GXmlElement::variantFromXml( shutterMarkerElement );
		setShutterMarkerVisible( showShutterMarker.toBool() );
	}
}
// ---------------------------------------------------------------------------


// --------------------- GRoiEditor::drawBackground() ------------------------
void GRoiEditor::drawBackground( QPainter * pPainter, const QRectF &rect )
{
	if( !pPainter ) return;
		// fill hole scene with black
	pPainter->fillRect( rect, QBrush( Qt::black ) );

		// draw frame and pixmap
	QRect frameRect;
	if( _pixmap.rect().isValid() )
	{
		frameRect = _pixmap.rect().adjusted( -2, -2, 2, 2 );
	}
	QRect sceneRect = this->sceneRect().toRect();
	if( !sceneRect.isEmpty() )
	{
		pPainter->setPen( QPen( Qt::lightGray, 3 ) );
		pPainter->drawRect( frameRect );
		
		pPainter->drawPixmap( sceneRect, _pixmap );
	}
}
// ---------------------------------------------------------------------------


// -------------------------- GRoiEditor::clear() ----------------------------
void GRoiEditor::clear()
{
		// hide tools 
	setToolsVisible( false );
	
	foreach( QGraphicsRectItem * pItem, _objectRects )
	{
		if( !pItem ) continue;
		if( pItem->scene() == this ) this->removeItem( pItem );
	}
	foreach( QGraphicsPathItem * pItem, _objectBarycentrums )
	{
		if( !pItem ) continue;
		if( pItem->scene() == this ) this->removeItem( pItem );
	}
	foreach( QGraphicsSimpleTextItem * pItem, _objectDescriptions )
	{
		if( !pItem ) continue;
		if( pItem->scene() == this ) this->removeItem( pItem );
	}
	foreach( QGraphicsPathItem * pItem, _objectTrace0 )
	{
		if( !pItem ) continue;
		if( pItem->scene() == this ) this->removeItem( pItem );
	}
	foreach( QGraphicsPathItem * pItem, _objectTrace1 )
	{
		if( !pItem ) continue;
		if( pItem->scene() == this ) this->removeItem( pItem );
	}
	foreach( QGraphicsPathItem * pItem, _objectTrace2 )
	{
		if( !pItem ) continue;
		if( pItem->scene() == this ) this->removeItem( pItem );
	}
	foreach( QGraphicsItem * pItem, _tools )
	{
		if( !pItem ) continue;
		if( pItem->scene() == this ) this->removeItem( pItem );
	}
	
		// simply set empty pixmap
	setPixmap( QPixmap() );
}
// ---------------------------------------------------------------------------


// ----------------------- GRoiEditor::setPixmap() ---------------------------
void GRoiEditor::setPixmap( const QPixmap & pixmap )
{
		// setup background  pixmap and default configuration
	_pixmap   = pixmap;
	_baseSize = _pixmap.size();
	
		// setup scene rect
	this->setSceneRect( _pixmap.rect() );

	setDefaultRegions();
	
		// call scene to update backGround
	this->setBackgroundBrush( QBrush() );
}
// ---------------------------------------------------------------------------


// ---------------------- GRoiEditor::setSize() ------------------------------
void GRoiEditor::setSize( const QSize & size )
{
	_baseSize = size;
	
		// setup scene rect 
	this->setSceneRect( QRect( QPoint( 0, 0 ), _baseSize ) );
	setDefaultRegions();
}
// ---------------------------------------------------------------------------


// ---------------------- GRoiEditor::updatePixmap() -------------------------
void GRoiEditor::updatePixmap( const QPixmap & pixmap )
{
		// do nothing for null pixmap
	if( pixmap.isNull() ) return;
	
		// if default configuration wasn't setup then set it up
	if( _baseSize.isEmpty() )
	{
		setPixmap( pixmap );
		return;
	}
	
		// scalse pixmap if is in different size than _baseSize
	if( pixmap.size() != _baseSize )
	{
		_pixmap = pixmap.scaled( _baseSize );
	}
	else
	{
		_pixmap = pixmap;
	}

		// call scene to update backGround
	this->setBackgroundBrush( QBrush() );
}
// ---------------------------------------------------------------------------


// -------------------- GRoiEditor::setToolsVisible() ------------------------
void GRoiEditor::setToolsVisible( bool visible )
{
	setRoiToolVisible( visible );
	setStartMarkerVisible( visible );
	setEndMarkerVisible( visible );
	setShutterMarkerVisible( visible );
}
// ---------------------------------------------------------------------------


// --------------- GRoiEditor::setRoiToolVisible() ---------------------------
void GRoiEditor::setRoiToolVisible( bool visible )
{
	if( _pRoi ) _pRoi->setVisible( visible );
}
// ---------------------------------------------------------------------------


// --------------- GRoiEditor::setStartMarkerVisible() -----------------------
void GRoiEditor::setStartMarkerVisible( bool visible )
{
	if( _pStartMarker ) _pStartMarker->setVisible( visible );
}
// ---------------------------------------------------------------------------


// --------------- GRoiEditor::setEndMarkerVisible() -------------------------
void GRoiEditor::setEndMarkerVisible( bool visible )
{
	if( _pEndMarker ) _pEndMarker->setVisible( visible );
}
// ---------------------------------------------------------------------------


// -------------- GRoiEditor::setShutterMarkerVisible() ----------------------
void GRoiEditor::setShutterMarkerVisible( bool visible )
{
	if( _pShutterMarker ) _pShutterMarker->setVisible( visible );
}
// ---------------------------------------------------------------------------


// --------------- GRoiEditor::isRoiToolVisible() ----------------------------
bool GRoiEditor::isRoiToolVisible()const
{
	if( _pRoi )
	{
		return _pRoi->isVisible();
	}
	return false;
}
// ---------------------------------------------------------------------------


// --------------- GRoiEditor::isStartMarkerVisible() ------------------------
bool GRoiEditor::isStartMarkerVisible()const
{
	if( _pStartMarker )
	{
		return _pStartMarker->isVisible();
	}
	return false;
}
// ---------------------------------------------------------------------------


// --------------- GRoiEditor::isEndMarkerVisible() --------------------------
bool GRoiEditor::isEndMarkerVisible()const
{
	if( _pEndMarker )
	{
		return _pEndMarker->isVisible();
	}
	return false;
}
// ---------------------------------------------------------------------------


// -------------- GRoiEditor::isShutterMarkerVisible() -----------------------
bool GRoiEditor::isShutterMarkerVisible()const
{
	if( _pShutterMarker )
	{
		return _pShutterMarker->isVisible();
	}
	return false;
}
// ---------------------------------------------------------------------------


// ------------------- GRoiEditor::showAccelExceeded() -----------------------
void GRoiEditor::showAccelExceeded()
{
		// get sceneRect and check if its OK
	QRectF sceneRect = this->sceneRect();
	if( !sceneRect.isValid() ) return;
	if( (sceneRect.width() < 60) || (sceneRect.height() < 50) ) return;

	if( !_pAccelExccededIcon )
	{
		QPixmap pixmap( ":res/accel_exceeded" );
		_pAccelExccededIcon = new QGraphicsPixmapItem( pixmap );
		_pAccelExccededIcon->setPos( sceneRect.width() - 60, 10 );
		_pAccelExccededIcon->setZValue( 999 );
		this->addItem( _pAccelExccededIcon );
	}
	
	_pAccelExccededIcon->show();
}
// ---------------------------------------------------------------------------

	
// ----------------------- GRoiEditor::hideAccelExceeded() -------------------
void GRoiEditor::hideAccelExceeded()
{
	if( !_pAccelExccededIcon ) return;

	_pAccelExccededIcon->hide();
}
// ---------------------------------------------------------------------------


// ------------------- GRoiEditor::showAlarm() -------------------------------
void GRoiEditor::showAlarm()
{
		// get sceneRect and check if its OK
	QRectF sceneRect = this->sceneRect();
	if( !sceneRect.isValid() ) return;
	if( (sceneRect.width() < 100) || (sceneRect.height() < 50) ) return;

	if( !_pAlarmIcon )
	{
		QPixmap pixmap( ":res/alarm.png" );
		_pAlarmIcon = new QGraphicsPixmapItem( pixmap );
		_pAlarmIcon->setPos( sceneRect.width() - 100, 10 );
		_pAlarmIcon->setZValue( 999 );
		this->addItem( _pAlarmIcon );
	}

	_pAlarmIcon->show();
}
// ---------------------------------------------------------------------------

	
// ----------------------- GRoiEditor::hideAlarm() ---------------------------
void GRoiEditor::hideAlarm()
{
	if( !_pAlarmIcon ) return;

	_pAlarmIcon->hide();
}
// ---------------------------------------------------------------------------
	

// ------------------------ GRoiEditor::setDefaultRegions() ------------------
void GRoiEditor::setDefaultRegions()
{
		// get _pixmaps sizes
	double w = this->sceneRect().width();
	double h = this->sceneRect().height();

		// if pixmap wasnt set leave 
	if( ( w == 0 ) || ( h == 0 ) ) return; 

		// set Roi
	QPolygonF nodes;
	nodes << QPointF( w*0.1, h*0.1 ) << QPointF( w - w*0.1, h*0.1 )
			<< QPointF( w - w*0.1, h - h*0.1 ) << QPointF( w*0.1, h - h*0.1 );
	setRoiNodes( nodes );
	
		// set default hooks position
	setStartMarkerHooks( QPointF( w*0.15, h*0.15 ),
						 QPointF( w - w*0.15, h*0.15 )
					   );
	setEndMarkerHooks( QPointF( w - w*0.15, h - h*0.15 ),
					   QPointF( w*0.15, h - h*0.15 )
					 );
	setShutterMarkerHooks( QPointF( w - w*0.15, h - h*0.1 ),
						   QPointF( w*0.15, h - h*0.1 )
						 );
}
// ---------------------------------------------------------------------------


// -------------------- GRoiEditor::setRoiNodes() ----------------------------
void GRoiEditor::setRoiNodes( const QPolygonF & nodes )
{
		// if Roi isn't present create one
	if( !_pRoi )
	{
		_pRoi = new GRoi();
		_tools << _pRoi;
		_pRoi->setName( "roi" );
		_pRoi->setZValue( 1.0 );
		this->addItem( _pRoi );
	}

	_pRoi->disconnect();
	_pRoi->setNodes( nodes );
	connect( _pRoi, SIGNAL( itemChanged() ),
				this, SIGNAL( roiChanged() ) );
}
// ---------------------------------------------------------------------------


// -------------------- GRoiEditor::setStartMarkerHooks() --------------------
void GRoiEditor::setStartMarkerHooks( const QPointF & pos1,
									  const QPointF & pos2 )
{
		// if start marker isn't present create one
	if( !_pStartMarker )
	{
		_pStartMarker = new GMarker( START_MARKER_COLOR );
		_tools << _pStartMarker;
		_pStartMarker->setName( "startMarker" );
		_pStartMarker->setToolTip( tr( "Start marker" ) );
		_pStartMarker->setZValue( 2.0 );
		this->addItem( _pStartMarker );
	}

	_pStartMarker->disconnect();
	_pStartMarker->setHooks( pos1, pos2 );
	connect( _pStartMarker, SIGNAL( itemChanged() ),
				this, SIGNAL( markersChanged() ) );
}
// ---------------------------------------------------------------------------


// ------------------- GRoiEditor::setEndMarkerHook() ------------------------
void GRoiEditor::setEndMarkerHooks( const QPointF & pos1,
									const QPointF & pos2 )
{
        // if end marker isn't present create one
    if( !_pEndMarker )
    {
		_pEndMarker = new GMarker( END_MARKER_COLOR );
		_tools << _pEndMarker;
		_pEndMarker->setName( "endMarker" );
		_pEndMarker->setToolTip( tr( "End marker." ) );
		_pEndMarker->setZValue( 2.0 );
		this->addItem( _pEndMarker );
    }

	_pEndMarker->disconnect();
	_pEndMarker->setHooks( pos1, pos2 );
	connect( _pEndMarker, SIGNAL( itemChanged() ),
				this, SIGNAL( markersChanged() ) );
}
// ---------------------------------------------------------------------------


// ------------------- GRoiEditor::setShutterMarkerHook() ------------------------
void GRoiEditor::setShutterMarkerHooks( const QPointF & pos1,
                                        const QPointF & pos2 )
{
        // if shutter marker isn't present create one
    if( !_pShutterMarker )
    {
		_pShutterMarker = new GMarker( SHUTTER_MARKER_COLOR );
		_tools << _pShutterMarker;
		_pShutterMarker->setName( "shutterMarker" );
		_pShutterMarker->setToolTip( tr( "Shutter marker. " ) );
		_pShutterMarker->setZValue( 2.0 );
		this->addItem( _pShutterMarker );
    }

	_pShutterMarker->disconnect();
	_pShutterMarker->setHooks( pos1, pos2 );
	connect( _pShutterMarker, SIGNAL( itemChanged() ),
				this, SIGNAL( shutterChanged() ) );
}
// ---------------------------------------------------------------------------


// -------------------- GRoiEditor::markersImage() ---------------------------
pimage_t GRoiEditor::markersImage()const
{
	if( !_pStartMarker | !_pEndMarker ) return create_image( 0, 0 );
	
		// create regions image in size of loaded image (_pixmap)
	QImage regionsImage( _pixmap.size(), QImage::Format_ARGB32_Premultiplied );
	
		// create painter
	QPainter painter( &regionsImage );
	painter.setPen( Qt::NoPen );
		// fill regionsImage transparently
	painter.setCompositionMode( QPainter::CompositionMode_Source );
	painter.fillRect( regionsImage.rect(), Qt::transparent );
		// draw start marker region
	painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
	painter.setBrush( Qt::red );
	painter.drawPath( _pStartMarker->markerRegion() );
		// set XOR composition mode and paint end marker region
	painter.setCompositionMode( QPainter::CompositionMode_Xor );
	painter.setBrush( Qt::blue );
	painter.drawPath(  _pEndMarker->markerRegion() );
		// paint background
	painter.setCompositionMode( QPainter::CompositionMode_DestinationOver );
	painter.fillRect( regionsImage.rect(), Qt::green );
	painter.end();
	
		// create image
	pimage_t pimage = create_image( regionsImage.width(), regionsImage.height() );
	
	// start marker region is red colored - is changed into indexed 0
	// central region is green colored - is changed into indexed 1
	// end marker region is blue colored - is changed into indexed 2
	// other colors are changed into indexed 3
	
		// copy data
	Q_ASSERT( pimage );
	for( int y = 0; y < pimage->height; y++ )
	{
		for( int x = 0 ; x < pimage->width; x++ )
		{
			if( regionsImage.pixel( x, y ) == qRgb( 255, 0, 0 ) )
				image_pixel( pimage, x, y ) = 0;
			else if( regionsImage.pixel( x, y ) == qRgb( 0, 255, 0 ) )
				image_pixel( pimage, x, y ) = 1;
			else if( regionsImage.pixel( x, y ) == qRgb( 0, 0, 255 ) )
				image_pixel( pimage, x, y ) = 2;
			else
				image_pixel( pimage, x, y ) = 3;
		}
	}
	
	return pimage;
}
// ---------------------------------------------------------------------------


// -------------------- GRoiEditor::shutterImage() ---------------------------
pimage_t GRoiEditor::shutterImage()const
{
	if( !_pShutterMarker ) return create_image( 0, 0 );
	
		// create shutter image in size of loaded image (_pixmap)
	QImage regionsImage( _pixmap.size(), QImage::Format_ARGB32_Premultiplied );
	
		// create painter
	QPainter painter( &regionsImage );
	painter.setPen( Qt::NoPen );
		// fill regionsImage transparently
	painter.setCompositionMode( QPainter::CompositionMode_Source );
	painter.fillRect( regionsImage.rect(), Qt::transparent );
		// draw shutter marker region
	painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
	painter.setBrush( Qt::green );
	painter.drawPath( _pShutterMarker->markerRegion() );
		// paint background
	painter.setCompositionMode( QPainter::CompositionMode_DestinationOver );
	painter.fillRect( regionsImage.rect(), Qt::red );
	painter.end();
	
		// create image
	pimage_t pimage = create_image( regionsImage.width(), regionsImage.height() );

	// region before shutter marker is red - changed into indexed 0
	// shutter marker region is green colored - is changed into indexed 1
	// other colors are changed into indexed 2
	
		// copy data
	Q_ASSERT( pimage );
	for( int y = 0; y < pimage->height; y++ )
	{
		for( int x = 0 ; x < pimage->width; x++ )
		{
			if( regionsImage.pixel( x, y ) == qRgb( 255, 0, 0 ) )
				image_pixel( pimage, x, y ) = 0;
			else if( regionsImage.pixel( x, y ) == qRgb( 0, 255, 0 ) )
				image_pixel( pimage, x, y ) = 1;
			else
				image_pixel( pimage, x, y ) = 2;
		}
	}

	return pimage;
}
// ---------------------------------------------------------------------------


// ---------------------- GRoiEditor::roiImage() -----------------------------
pimage_t GRoiEditor::roiImage()const
{
	if( !_pRoi ) return create_image( 0, 0 );
	
	
		// create regions image in size of loaded image (_pixmap)
	QImage regionsImage( _pixmap.size(), QImage::Format_RGB32 );
	
		// create painter
	QPainter painter( &regionsImage );
	painter.setPen( Qt::NoPen );
		// fill regionsImage with red (indexed 0),
		// at default hole image is outer region
	painter.fillRect( regionsImage.rect(), Qt::red );
		// draw roi region
	painter.setBrush( Qt::green );
	painter.drawPath( _pRoi->roiRegion() );
	painter.end();
	
		// create image
	pimage_t pimage = create_image( regionsImage.width(), regionsImage.height() );
	
	// region not interested is red colored - is changed into indexed 0
	// central region is green colored - is changed into indexed 1
	// other colors are changed into indexed 2
	
		// copy data
	Q_ASSERT( pimage );
	for( int y = 0; y < pimage->height; y++ )
	{
		for( int x = 0 ; x < pimage->width; x++ )
		{
			if( regionsImage.pixel( x, y ) == qRgb( 255, 0, 0 ) )
			{
				image_pixel( pimage, x, y ) = 0;
			}
			else if( regionsImage.pixel( x, y ) == qRgb( 0, 255, 0 ) )
			{
				image_pixel( pimage, x, y ) = 1;
			}
			else
			{
				image_pixel( pimage, x, y ) = 2;
			}
		}
	}
	
	return pimage;
}
// ---------------------------------------------------------------------------


// ----------------------- GRoiEditor::roiNodes() ----------------------------
QPolygonF GRoiEditor::roiNodes()const
{
	if( !_pRoi ) return QPolygonF();
	return _pRoi->nodes();
}
// ---------------------------------------------------------------------------


// ----------------------- GRoiEditor::startMarkerHooks() --------------------
QPolygonF GRoiEditor::startMarkerHooks()const
{
	if( !_pStartMarker ) return QPolygonF();
	return _pStartMarker->hooks();
}
// ---------------------------------------------------------------------------


// ---------------------- GRoiEditor::endMarkerHooks() -----------------------
QPolygonF GRoiEditor::endMarkerHooks()const
{
	if( !_pEndMarker ) return QPolygonF();
	return _pEndMarker->hooks();
}
// ---------------------------------------------------------------------------


// ---------------------- GRoiEditor::shutterMarkerHooks() -------------------
QPolygonF GRoiEditor::shutterMarkerHooks()const
{
	if( !_pShutterMarker ) return QPolygonF();
	return _pShutterMarker->hooks();
}
// ---------------------------------------------------------------------------


// ----------------------- GRoiEditor::updateObjects() -----------------------
void GRoiEditor::updateObjects( QList<objectCoordinates> & _objects )
{
	int objectsNum = _objects.size();
	int currentObjectsNum = _objectRects.size();
	if( currentObjectsNum < objectsNum ) // resize element lists if _objects is bigger
	{
		QPen rectPen( Qt::red );

		QPen barycentrumPen( Qt::green );
		QPainterPath barycentrumCross;
		barycentrumCross.moveTo( -5, -5 );
		barycentrumCross.lineTo(  5,  5 );
		barycentrumCross.moveTo( -5,  5 );
		barycentrumCross.lineTo(  5, -5 );

		QPen descriptionPen( Qt::white );
		QFont descriptionFont( "luxi mono" );
		descriptionFont.setPointSize( 10 );

		for( int i = currentObjectsNum; i < objectsNum; i++ )
		{
			QGraphicsRectItem * pNewRect = new QGraphicsRectItem();
			pNewRect->setPen( rectPen );
			this->addItem( pNewRect );
			_objectRects.append( pNewRect );
			
			QGraphicsPathItem * pNewBarycentrum = new QGraphicsPathItem();
			pNewBarycentrum->setPath( barycentrumCross );
			pNewBarycentrum->setPen( barycentrumPen );
			this->addItem( pNewBarycentrum );
			_objectBarycentrums.append( pNewBarycentrum );
			
			QGraphicsSimpleTextItem * pNewDescription = new QGraphicsSimpleTextItem();
			pNewDescription->setPen( descriptionPen );
			pNewDescription->setBrush( QColor( Qt::white ) );
			pNewDescription->setFont( descriptionFont );
			this->addItem( pNewDescription );
			_objectDescriptions.append( pNewDescription );

				// trace in range of start marker
			QGraphicsPathItem * pNewTrace0 = new QGraphicsPathItem();
			pNewTrace0->setPen( QPen( START_MARKER_COLOR ) );
			this->addItem( pNewTrace0 );
			_objectTrace0.append( pNewTrace0 );
				// trace in range between start and end markers
			QGraphicsPathItem * pNewTrace1 = new QGraphicsPathItem();
			pNewTrace1->setPen( QPen( BETWEEN_MARKERS_COLOR ) );
			this->addItem( pNewTrace1 );
			_objectTrace1.append( pNewTrace1 );
				// trace in range of end marker
			QGraphicsPathItem * pNewTrace2 = new QGraphicsPathItem();
			pNewTrace2->setPen( QPen( END_MARKER_COLOR ) );
			this->addItem( pNewTrace2 );
			_objectTrace2.append( pNewTrace2 );
			
		} // !for
	}
	else if( currentObjectsNum > objectsNum ) // if there's not so many items
	{
		 // make invisible not presented ones

		for( int i  = objectsNum; i < currentObjectsNum; i++ )
		{
			if( _objectRects.at( i ) )
			{
				_objectRects.at( i )->setVisible( false );
			}
			if( _objectBarycentrums.at( i ) )
			{
				_objectBarycentrums.at( i )->setVisible( false );
			}
			if( _objectDescriptions.at( i ) )
			{
				_objectDescriptions.at( i )->setVisible( false );
			}
			if( _objectTrace0.at( i ) )
			{
				_objectTrace0.at( i )->setVisible( false );
			}
			if( _objectTrace1.at( i ) )
			{
				_objectTrace1.at( i )->setVisible( false );
			}
			if( _objectTrace2.at( i ) )
			{
				_objectTrace2.at( i )->setVisible( false );
			}
		}
	}

		// setup items
	for( int i = 0; i < objectsNum; i++ )
	{
		if( _objectRects.at( i ) )
		{
			_objectRects.at( i )->setRect( _objects.at( i ).positionRect );
			_objectRects.at( i )->setVisible( true );
		}
		
		if( _objectBarycentrums.at( i ) )
		{
			_objectBarycentrums.at( i )->setPos( _objects.at( i ).barycentrumPoint );
			_objectBarycentrums.at( i )->setVisible( true );
		}
		
		if( _objectDescriptions.at( i ) )
		{
			_objectDescriptions.at( i )->setText( _objects.at( i ).description );
			
			double xPos = _objects.at( i ).positionRect.x();
			xPos += _objects.at( i ).positionRect.width() / 2;
			xPos -= _objectDescriptions.at( i )->boundingRect().width() / 2;
			
			double yPos = _objects.at( i ).positionRect.y() - 20;
			
			_objectDescriptions.at( i )->setPos( xPos, yPos );
			_objectDescriptions.at( i )->setVisible( true );
		}
		if( _objectTrace0.at( i ) )
		{
			_objectTrace0.at( i )->setPath( processTrace( _objects.at( i ), 0 ) );
			_objectTrace0.at( i )->setVisible( true );
		}
		if( _objectTrace1.at( i ) )
		{
			_objectTrace1.at( i )->setPath( processTrace( _objects.at( i ), 1 ) );
			_objectTrace1.at( i )->setVisible( true );
		}
		if( _objectTrace2.at( i ) )
		{
			_objectTrace2.at( i )->setPath( processTrace( _objects.at( i ), 2 ) );
			_objectTrace2.at( i )->setVisible( true );
		}
	}
}
// ---------------------------------------------------------------------------


// ------------------ GRoiEditor::processTrace() -----------------------------
QPainterPath GRoiEditor::processTrace( objectCoordinates coordinates,
									   qint16 wantedZone
									 )
{
	QPainterPath tracePath;

		// get trace from coordintates 
	QList< QPair< QPoint, qint16 > > trace = coordinates.trace;

	qint16 previousZone = -1;
	QPair< QPoint, qint16 > point;
	foreach( point, trace )
	{
			// get current zone
		qint16 currentZone = point.second;
		if( previousZone != currentZone ) // zone changed
		{
			if( currentZone == wantedZone ) // proceed if in wanted zone
			{
				tracePath.closeSubpath();
				tracePath.moveTo( point.first );
			}
		}
		else // currentZone the same
		{
			if( currentZone == wantedZone ) // proceed if in wanted zone
			{
				tracePath.lineTo( point.first );
			}
		}
			// store zone number 
		previousZone = currentZone;
	}

	return tracePath;
}
// ---------------------------------------------------------------------------





// eof
